"""
协调API路由

提供智能体协调和任务管理的API接口。
"""

from typing import Dict, List, Any, Optional
from datetime import datetime
from fastapi import APIRouter, HTTPException, Depends, Query, Path
from pydantic import BaseModel, Field

from ..coordination.coordination_engine import CoordinationEngine
from ..coordination.coordination_patterns import CoordinationMode, CoordinationContext
from ..coordination.task_analyzer import TaskAnalyzer
from ..coordination.mode_selector import ModeSelector
from ..coordination.conflict_resolver import ConflictResolver
from ..dependencies import get_coordination_engine, get_task_analyzer, get_mode_selector, get_conflict_resolver


router = APIRouter(prefix="/coordination", tags=["coordination"])


# 请求模型
class CoordinationRequest(BaseModel):
    """协调请求模型"""
    task_id: str = Field(..., description="任务ID")
    agent_ids: List[str] = Field(..., description="参与智能体ID列表")
    coordination_mode: Optional[str] = Field(None, description="协调模式")
    priority: int = Field(default=5, ge=1, le=10, description="任务优先级")
    deadline: Optional[datetime] = Field(None, description="截止时间")
    context: Dict[str, Any] = Field(default_factory=dict, description="协调上下文")


class TaskAnalysisRequest(BaseModel):
    """任务分析请求模型"""
    task_description: str = Field(..., description="任务描述")
    requirements: Dict[str, Any] = Field(default_factory=dict, description="任务需求")
    constraints: Dict[str, Any] = Field(default_factory=dict, description="任务约束")


class ModeSelectionRequest(BaseModel):
    """模式选择请求模型"""
    task_type: str = Field(..., description="任务类型")
    agent_count: int = Field(..., ge=1, description="智能体数量")
    complexity: str = Field(..., description="任务复杂度")
    time_constraints: Dict[str, Any] = Field(default_factory=dict, description="时间约束")
    resource_constraints: Dict[str, Any] = Field(default_factory=dict, description="资源约束")


class ConflictResolutionRequest(BaseModel):
    """冲突解决请求模型"""
    conflict_type: str = Field(..., description="冲突类型")
    involved_agents: List[str] = Field(..., description="涉及的智能体")
    conflict_data: Dict[str, Any] = Field(..., description="冲突数据")
    resolution_strategy: Optional[str] = Field(None, description="解决策略")


# 响应模型
class CoordinationResponse(BaseModel):
    """协调响应模型"""
    coordination_id: str
    task_id: str
    status: str
    coordination_mode: str
    agent_assignments: Dict[str, Any]
    execution_plan: Dict[str, Any]
    estimated_duration: Optional[float] = None
    created_at: datetime
    updated_at: Optional[datetime] = None


class TaskAnalysisResponse(BaseModel):
    """任务分析响应模型"""
    analysis_id: str
    task_type: str
    complexity: str
    estimated_duration: float
    required_capabilities: List[str]
    recommended_agents: List[str]
    resource_requirements: Dict[str, Any]
    risk_factors: List[str]
    success_probability: float
    analysis_time: datetime


class ModeSelectionResponse(BaseModel):
    """模式选择响应模型"""
    recommended_mode: str
    confidence_score: float
    alternative_modes: List[Dict[str, Any]]
    reasoning: str
    mode_characteristics: Dict[str, Any]
    selection_time: datetime


class ConflictResolutionResponse(BaseModel):
    """冲突解决响应模型"""
    resolution_id: str
    conflict_type: str
    resolution_strategy: str
    resolution_steps: List[Dict[str, Any]]
    affected_agents: List[str]
    estimated_impact: Dict[str, Any]
    status: str
    created_at: datetime
    resolved_at: Optional[datetime] = None


class CoordinationStatus(BaseModel):
    """协调状态模型"""
    active_coordinations: int
    pending_tasks: int
    completed_tasks: int
    failed_tasks: int
    average_completion_time: float
    success_rate: float
    mode_distribution: Dict[str, int]
    agent_utilization: Dict[str, float]


# API端点
@router.post("/coordinate", response_model=CoordinationResponse)
async def coordinate_task(
    request: CoordinationRequest,
    engine: CoordinationEngine = Depends(get_coordination_engine)
) -> CoordinationResponse:
    """
    协调任务执行
    
    Args:
        request: 协调请求
        engine: 协调引擎
        
    Returns:
        协调响应
    """
    try:
        # 创建协调上下文
        context = CoordinationContext(
            task_id=request.task_id,
            agent_ids=request.agent_ids,
            priority=request.priority,
            deadline=request.deadline,
            metadata=request.context
        )
        
        # 确定协调模式
        if request.coordination_mode:
            try:
                coordination_mode = CoordinationMode(request.coordination_mode)
            except ValueError:
                raise HTTPException(status_code=400, detail=f"无效的协调模式: {request.coordination_mode}")
        else:
            coordination_mode = None
        
        # 执行协调
        coordination = await engine.coordinate_task(
            context=context,
            coordination_mode=coordination_mode
        )
        
        return CoordinationResponse(
            coordination_id=coordination.coordination_id,
            task_id=coordination.task_id,
            status=coordination.status.value,
            coordination_mode=coordination.coordination_mode.value,
            agent_assignments=coordination.agent_assignments,
            execution_plan=coordination.execution_plan,
            estimated_duration=coordination.estimated_duration,
            created_at=coordination.created_at,
            updated_at=coordination.updated_at
        )
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"任务协调失败: {str(e)}")


@router.get("/coordinations/{coordination_id}", response_model=CoordinationResponse)
async def get_coordination(
    coordination_id: str = Path(..., description="协调ID"),
    engine: CoordinationEngine = Depends(get_coordination_engine)
) -> CoordinationResponse:
    """
    获取协调详情
    
    Args:
        coordination_id: 协调ID
        engine: 协调引擎
        
    Returns:
        协调信息
    """
    try:
        coordination = await engine.get_coordination(coordination_id)
        if not coordination:
            raise HTTPException(status_code=404, detail=f"协调 {coordination_id} 不存在")
        
        return CoordinationResponse(
            coordination_id=coordination.coordination_id,
            task_id=coordination.task_id,
            status=coordination.status.value,
            coordination_mode=coordination.coordination_mode.value,
            agent_assignments=coordination.agent_assignments,
            execution_plan=coordination.execution_plan,
            estimated_duration=coordination.estimated_duration,
            created_at=coordination.created_at,
            updated_at=coordination.updated_at
        )
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取协调详情失败: {str(e)}")


@router.post("/analyze", response_model=TaskAnalysisResponse)
async def analyze_task(
    request: TaskAnalysisRequest,
    analyzer: TaskAnalyzer = Depends(get_task_analyzer)
) -> TaskAnalysisResponse:
    """
    分析任务
    
    Args:
        request: 任务分析请求
        analyzer: 任务分析器
        
    Returns:
        任务分析结果
    """
    try:
        # 执行任务分析
        analysis = await analyzer.analyze_task(
            task_description=request.task_description,
            requirements=request.requirements,
            constraints=request.constraints
        )
        
        return TaskAnalysisResponse(
            analysis_id=analysis.analysis_id,
            task_type=analysis.task_type,
            complexity=analysis.complexity,
            estimated_duration=analysis.estimated_duration,
            required_capabilities=analysis.required_capabilities,
            recommended_agents=analysis.recommended_agents,
            resource_requirements=analysis.resource_requirements,
            risk_factors=analysis.risk_factors,
            success_probability=analysis.success_probability,
            analysis_time=analysis.analysis_time
        )
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"任务分析失败: {str(e)}")


@router.post("/select-mode", response_model=ModeSelectionResponse)
async def select_coordination_mode(
    request: ModeSelectionRequest,
    selector: ModeSelector = Depends(get_mode_selector)
) -> ModeSelectionResponse:
    """
    选择协调模式
    
    Args:
        request: 模式选择请求
        selector: 模式选择器
        
    Returns:
        模式选择结果
    """
    try:
        # 创建协调上下文
        context = CoordinationContext(
            task_id=f"temp_{datetime.now().timestamp()}",
            agent_ids=[f"agent_{i}" for i in range(request.agent_count)],
            metadata={
                "task_type": request.task_type,
                "complexity": request.complexity,
                "time_constraints": request.time_constraints,
                "resource_constraints": request.resource_constraints
            }
        )
        
        # 选择协调模式
        selection = await selector.select_mode(context)
        
        return ModeSelectionResponse(
            recommended_mode=selection.recommended_mode.value,
            confidence_score=selection.confidence_score,
            alternative_modes=[
                {
                    "mode": alt.mode.value,
                    "score": alt.score,
                    "reason": alt.reason
                }
                for alt in selection.alternative_modes
            ],
            reasoning=selection.reasoning,
            mode_characteristics=selection.mode_characteristics,
            selection_time=selection.selection_time
        )
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"模式选择失败: {str(e)}")


@router.post("/resolve-conflict", response_model=ConflictResolutionResponse)
async def resolve_conflict(
    request: ConflictResolutionRequest,
    resolver: ConflictResolver = Depends(get_conflict_resolver)
) -> ConflictResolutionResponse:
    """
    解决冲突
    
    Args:
        request: 冲突解决请求
        resolver: 冲突解决器
        
    Returns:
        冲突解决结果
    """
    try:
        # 执行冲突解决
        resolution = await resolver.resolve_conflict(
            conflict_type=request.conflict_type,
            involved_agents=request.involved_agents,
            conflict_data=request.conflict_data,
            resolution_strategy=request.resolution_strategy
        )
        
        return ConflictResolutionResponse(
            resolution_id=resolution.resolution_id,
            conflict_type=resolution.conflict_type,
            resolution_strategy=resolution.resolution_strategy,
            resolution_steps=resolution.resolution_steps,
            affected_agents=resolution.affected_agents,
            estimated_impact=resolution.estimated_impact,
            status=resolution.status,
            created_at=resolution.created_at,
            resolved_at=resolution.resolved_at
        )
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"冲突解决失败: {str(e)}")


@router.get("/coordinations", response_model=List[CoordinationResponse])
async def list_coordinations(
    status: Optional[str] = Query(None, description="状态筛选"),
    mode: Optional[str] = Query(None, description="模式筛选"),
    limit: int = Query(20, ge=1, le=100, description="返回数量限制"),
    offset: int = Query(0, ge=0, description="偏移量"),
    engine: CoordinationEngine = Depends(get_coordination_engine)
) -> List[CoordinationResponse]:
    """
    获取协调列表
    
    Args:
        status: 状态筛选
        mode: 模式筛选
        limit: 数量限制
        offset: 偏移量
        engine: 协调引擎
        
    Returns:
        协调列表
    """
    try:
        coordinations = await engine.list_coordinations(
            status=status,
            mode=mode,
            limit=limit,
            offset=offset
        )
        
        coordination_responses = []
        for coordination in coordinations:
            response = CoordinationResponse(
                coordination_id=coordination.coordination_id,
                task_id=coordination.task_id,
                status=coordination.status.value,
                coordination_mode=coordination.coordination_mode.value,
                agent_assignments=coordination.agent_assignments,
                execution_plan=coordination.execution_plan,
                estimated_duration=coordination.estimated_duration,
                created_at=coordination.created_at,
                updated_at=coordination.updated_at
            )
            coordination_responses.append(response)
        
        return coordination_responses
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取协调列表失败: {str(e)}")


@router.delete("/coordinations/{coordination_id}")
async def cancel_coordination(
    coordination_id: str = Path(..., description="协调ID"),
    engine: CoordinationEngine = Depends(get_coordination_engine)
) -> Dict[str, str]:
    """
    取消协调
    
    Args:
        coordination_id: 协调ID
        engine: 协调引擎
        
    Returns:
        取消结果
    """
    try:
        coordination = await engine.get_coordination(coordination_id)
        if not coordination:
            raise HTTPException(status_code=404, detail=f"协调 {coordination_id} 不存在")
        
        success = await engine.cancel_coordination(coordination_id)
        if not success:
            raise HTTPException(status_code=500, detail="协调取消失败")
        
        return {"message": f"协调 {coordination_id} 已取消"}
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"取消协调失败: {str(e)}")


@router.get("/modes/available")
async def get_available_coordination_modes() -> List[Dict[str, str]]:
    """
    获取可用的协调模式
    
    Returns:
        协调模式列表
    """
    try:
        modes = []
        for mode in CoordinationMode:
            modes.append({
                "value": mode.value,
                "name": mode.name,
                "description": f"{mode.value}协调模式"
            })
        
        return modes
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取协调模式失败: {str(e)}")


@router.get("/status", response_model=CoordinationStatus)
async def get_coordination_status(
    engine: CoordinationEngine = Depends(get_coordination_engine)
) -> CoordinationStatus:
    """
    获取协调状态统计
    
    Args:
        engine: 协调引擎
        
    Returns:
        协调状态信息
    """
    try:
        status = await engine.get_coordination_status()
        
        return CoordinationStatus(
            active_coordinations=status.get("active_coordinations", 0),
            pending_tasks=status.get("pending_tasks", 0),
            completed_tasks=status.get("completed_tasks", 0),
            failed_tasks=status.get("failed_tasks", 0),
            average_completion_time=status.get("average_completion_time", 0.0),
            success_rate=status.get("success_rate", 0.0),
            mode_distribution=status.get("mode_distribution", {}),
            agent_utilization=status.get("agent_utilization", {})
        )
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取协调状态失败: {str(e)}")


@router.get("/metrics")
async def get_coordination_metrics(
    start_date: Optional[datetime] = Query(None, description="开始时间"),
    end_date: Optional[datetime] = Query(None, description="结束时间"),
    engine: CoordinationEngine = Depends(get_coordination_engine)
) -> Dict[str, Any]:
    """
    获取协调指标
    
    Args:
        start_date: 开始时间
        end_date: 结束时间
        engine: 协调引擎
        
    Returns:
        协调指标数据
    """
    try:
        metrics = await engine.get_coordination_metrics(
            start_date=start_date,
            end_date=end_date
        )
        
        return {
            "period": {
                "start_date": start_date,
                "end_date": end_date
            },
            "task_metrics": metrics.get("task_metrics", {}),
            "mode_metrics": metrics.get("mode_metrics", {}),
            "agent_metrics": metrics.get("agent_metrics", {}),
            "performance_metrics": metrics.get("performance_metrics", {}),
            "efficiency_metrics": metrics.get("efficiency_metrics", {}),
            "quality_metrics": metrics.get("quality_metrics", {})
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取协调指标失败: {str(e)}")


@router.post("/optimize")
async def optimize_coordination(
    optimization_target: str = Query(..., description="优化目标"),
    constraints: Dict[str, Any] = {},
    engine: CoordinationEngine = Depends(get_coordination_engine)
) -> Dict[str, Any]:
    """
    优化协调策略
    
    Args:
        optimization_target: 优化目标
        constraints: 约束条件
        engine: 协调引擎
        
    Returns:
        优化结果
    """
    try:
        optimization = await engine.optimize_coordination(
            target=optimization_target,
            constraints=constraints
        )
        
        return {
            "optimization_id": optimization.get("optimization_id"),
            "target": optimization_target,
            "current_performance": optimization.get("current_performance", {}),
            "optimized_performance": optimization.get("optimized_performance", {}),
            "improvement": optimization.get("improvement", {}),
            "recommendations": optimization.get("recommendations", []),
            "implementation_plan": optimization.get("implementation_plan", {}),
            "estimated_impact": optimization.get("estimated_impact", {}),
            "optimization_time": datetime.now()
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"协调优化失败: {str(e)}")